package org.ourgrid.gridMonitor.operations;

import java.io.IOException;
import java.util.Collection;

import org.jivesoftware.smack.ReconnectionManager;
import org.ourgrid.common.interfaces.to.UserInfo;
import org.ourgrid.common.interfaces.to.WorkerInfo;
import org.ourgrid.common.spec.worker.WorkerSpec;
import org.ourgrid.gridMonitor.Componente;
import org.ourgrid.gridMonitor.LocalComponentInformation;
import org.ourgrid.gridMonitor.TipoMonitorado;
import org.ourgrid.gridMonitor.TipoOperacao;
import org.ourgrid.gridMonitor.client.ClientSocket;
import org.ourgrid.peer.ui.async.client.PeerAsyncInitializer;


public class PeerLocalOperation extends Thread{
	
	 private String mensagem[];
	 private static boolean sentPeerUserInformation = false;  //fica true se já enviou as informações do usuario do peer
	 private static boolean sentPeerWorkerInformation = false;  //fica true se já enviou as informações do usuario do worker

	 public PeerLocalOperation(String[] mensagem){
		 this.mensagem = mensagem;
	 }
	 
	 
	 public void run(){
		 processRequest();
	 }
	
     public void processRequest(){
    	 if((mensagem != null) && (mensagem.length > 0)){
    		 int operation = Integer.parseInt(mensagem[0]);
    		 try {
    			 if(operation == TipoOperacao.COMPONENT_JOIN){
    				 System.out.println("JOIN");
    				 String hamsterPath = mensagem[1];
    				 Componente.hamsterPath = hamsterPath;
    			 } else if(operation == TipoOperacao.COMPONENT_CONNECTION_REFUSED){ //Se a conexão foi recusada
    	        	 //O componente é considerado independente.
    				 System.out.println("CONNECTION_REFUSED");
    	         } else if (operation == TipoOperacao.GRID_MONITOR_RECONNECT){ //Caso a mensagem informe que o openfire mudou de localização...
    	        	 System.out.println("MONITOR_RECONNECT");
		        	 connect(Componente.tipoMonitorado,Componente.portaComunicacao);
    			 } else if (operation == TipoOperacao.NEW_OPENFIRE_LOCATION){ //Caso a mensagem informe que o openfire mudou de localização...
    				 System.out.println("OPENFIRE_LOCATION");
		        	 ReconnectionManager.newHost = mensagem[5];
		        	 ReconnectionManager.isNewHost = true;
		         } else if (operation == TipoOperacao.RETRIEVE_PEER_USERS){ //(OK) Caso a mensagem informe que o openfire mudou de localização...
		        	 //Recebe uma mensagem do monitor local
		        	 int quantidadeUsuarios = Integer.parseInt(mensagem[5]);
		        	 int index = 5;
		        	 
		        	 while(quantidadeUsuarios > 0){
		        		 String login = mensagem[index+1];
		        		 String password = mensagem[index+2];
		        		 
		        		 //Adiciona os usuários do peer
			        	 PeerAsyncInitializer.getInstance().getComponentClient().addUser(login, password);
			        	 
			        	 index = index + 2;
			        	 quantidadeUsuarios--;
		        	 }
		        	 //Conta quantos usuários tem na lista e adiciona um a um
		         } else if (operation == TipoOperacao.RETRIEVE_PEER_WORKERS){ //(OK) Caso a mensagem informe que o openfire mudou de localização...
		        	//Recebe uma mensagem do monitor local
		        	 int quantidadeUsuarios = Integer.parseInt(mensagem[5]);
		        	 int index = 5;
		        	 
		        	 while(quantidadeUsuarios > 0){
		        		 String user = mensagem[index+1];
		        		 String server = mensagem[index+2];
		        		 
		        		 //Adiciona os usuários do peer
		        		 WorkerSpec workerSpec = new WorkerSpec();
		        		 workerSpec.addAnnotation("user", user); //Verificar se isto funciona
		        		 workerSpec.addAnnotation("server", server);//Verificar se isto funciona
		        		 
			        	 PeerAsyncInitializer.getInstance().getComponentClient().addWorker(workerSpec);
			        	 
			        	 index = index + 2;
			        	 quantidadeUsuarios--;
		        	 }
		         }
    		 } catch (IOException e) {
					e.printStackTrace();
			 }
    	 }
     }
     
     /**
      * 
      * Method used to send informations about the new peer user
      * 
      * */
     public static void addPeerUser(String login, String password){
    	 String message = TipoOperacao.NEW_PEER_USER_ADDED+"#"+login+"#"+password;
         try {
			ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, message);
		} catch (IOException e) {
			e.printStackTrace();
		}	 
     }
     
     /**
      * Methos used to request the remotion of a peer user.
      * @param login
      */
     public static void removePeerUser(String login){
    	 String message = TipoOperacao.PEER_USER_DELETED+"#"+login;
         try {
			ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, message);
		} catch (IOException e) {
			e.printStackTrace();
		} 
     }
     
     /**
      * 
      *  This method ask to grid monitor the list of peer users
      * 
      */
     public static void requestPeerUser(){
    	String mensagem = TipoOperacao.REQUEST_PEER_USERS+"";
    	try{
    		ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
    	}catch(IOException e){
    		e.printStackTrace();
    	}
     }
     
     /**
      * This method is used to send informations about a worker added in a peer
      * 
      * @param worker
      */
     public static void addPeerWorker(WorkerSpec worker){
    	 worker.getUser();
    	 worker.getServer();
    	 String mensagem = TipoOperacao.NEW_PEER_WORKER_ADDED+"#"+worker.getUser()+"#"+worker.getServer();
     	try{
     		ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
     	}catch(IOException e){
     		e.printStackTrace();
     	}
     }
     
     
     /**
      * 
      * This method ask to grid monitor nodes to delete the information about the peer worker passed as parameter
      * 
      * @param user
      */
     public static void removePeerWorker(String user){
    	 String mensagem = TipoOperacao.NEW_PEER_WORKER_DELETED+"#"+user;
      	try{
      		ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
      	}catch(IOException e){
      		e.printStackTrace();
      	} 
     }
     
     
     /**
      * 
      * This method asks to the grid monitor if exist saved workers in another machines
      * 
      */
     public static void requestPeerWorkers(){
     	String mensagem = TipoOperacao.REQUEST_PEER_WORKERS+"";
     	try{
     		ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
     	}catch(IOException e){
     		e.printStackTrace();
     	}
     } 
     
     //Manda as informações dos usuarios do Peer para o hamster salvar
     public static void sendPeerUserInformation(Collection<UserInfo> data)
     {
    	 if (!sentPeerUserInformation)
    	 {
    		 String mensagem = TipoOperacao.SEND_PEER_USER_INFORMATION + "";
    		 for (UserInfo usr : data)
    		 {
    			 mensagem += "#" + usr.getUsername() + "#" + usr.getXMPPServer();
    		 }

    		 System.out.println("Testando a mensagem.\n" + mensagem);

    		 try{
    			 //System.out.println("Testando a mensagem.\n" + mensagem);
    			ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
    		 }catch(IOException e){
    			 e.printStackTrace();
    		 }
    		 finally{
    			 sentPeerUserInformation = true;
    		 }
    	 }
     }
     
     public static void sendPeerWorkerInformation(Collection<WorkerInfo> data)
     {
    	 if (!sentPeerWorkerInformation)
    	 {
    		 String mensagem = TipoOperacao.SEND_PEER_WORKER_INFORMATION + "";
    		 for (WorkerInfo usr : data)
    		 {
    			 mensagem += "#" + usr.getWorkerSpec().getUser() + "#" + usr.getWorkerSpec().getServer();
    		 }

    		 System.out.println("Testando a mensagem Workers.\n" + mensagem);

    		 try{
    			// System.out.println("Testando a mensagem Workers.\n" + mensagem);
    			 ClientSocket.enviarMSG("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
    		 }catch(IOException e){
    			 e.printStackTrace();
    		 }
    		 finally{
    			 sentPeerWorkerInformation = true;
    		 }
    	 }
     }
     
     public static void connect(int tipoMonitorado, int portaComunicacao) throws IOException{
    	 //The messagem will be 1#type#port#server#login#password
    	 String mensagem = TipoOperacao.COMPONENT_JOIN+Componente.separador+tipoMonitorado+Componente.separador+portaComunicacao+Componente.separador;
    	 mensagem = mensagem + LocalComponentInformation.servername+Componente.separador+LocalComponentInformation.login+Componente.separador+LocalComponentInformation.password;
      	 ClientSocket.mensagemConexao("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
      	 System.out.println("Conectar ao Hamster");
     }
     
     public static void savePeerInformation(){
    	 //28#tipo#port#login#pass#servername
    	 String mensagem = TipoOperacao.UPDATE_COMPONENTE_INFORMATION+Componente.separador+TipoMonitorado.PEER+Componente.separador+Componente.portaComunicacao+Componente.separador;
    	 mensagem = mensagem + LocalComponentInformation.login+Componente.separador+LocalComponentInformation.password+Componente.separador+LocalComponentInformation.servername;
      	 ClientSocket.mensagemConexao("127.0.0.1", LocalComponentInformation.INTERNAL_PORT, mensagem);
     }
     
}

